package com.wthink.hzgj.service


import android.widget.Toast
import com.wthink.hzgj.BusApplication
import com.wthink.hzgj.Constants
import com.wthink.hzgj.data.Result
import com.wthink.hzgj.util.HashUtil
import com.wthink.hzgj.util.Log
import com.wthink.hzgj.util.decodeBase64ToByteArray
import com.wthink.ubus.Method
import com.wthink.ubus.MethodParam
import com.wthink.ubus.ParamType
import com.wthink.ubus.server.Provider
import connectableflow.publish
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import java.io.*


object ScreenProvider {
    private lateinit var provider: Provider

    var cameraCtlFlow: Flow<String> = callbackFlow<String> {
        provider = Provider(
            "screen", listOf(
                Method(
                    "upgrade", listOf(
                        MethodParam("sig", ParamType.STRING),
                        MethodParam("size", ParamType.STRING),
                        MethodParam("ver", ParamType.INT)
                    )
                ),
                Method(
                    "show_camera", emptyList()
                ),
                Method(
                    "close_camera", emptyList()
                )
            )
        ) { id: Long, method: String, payload: String ->
            when (method) {
                "upgrade" -> {
                    val verInfo = MessageHelp.parseAppverInfo(payload)
                        upgrade(id, verInfo.ver, verInfo.sig, verInfo.size)

                }
                "show_camera" -> {
                    provider.rsp(id, "{\"success\": true}")
                    offer("show_camera")
                }
                "close_camera" -> {
                    provider.rsp(id, "{\"success\": true}")
                    offer("close_camera")
                }
            }
        }

        awaitClose { }
    }.publish().apply { connect(GlobalScope) }

    private fun upgrade(id: Long, ver: Int, sig: String, size: Long) {
        val appVer = getAppVersion()
        if (ver <= appVer) {
            provider.rsp(id, "{\"success\": false, \"err\":\"版本低于目前版本\"}")
            return
        }

        provider.rsp(id, "{\"success\": true}")

        upgrade(ver, sig, size)
    }

    private fun upgrade(ver: Int, sig: String, size: Long) {
        //val verFile = File("${Constants.UPDATE_URL}/app/${ver}.${sig}.${size}")
        val verdir = File("${Constants.UPDATE_URL}")
        val verFile = File("${Constants.UPDATE_URL}/${ver}.${sig}.${size}"+".apk")
        /*if (!verdir.exists()) {
            verdir.mkdirs()
        }*/

        if (!verFile.exists()) {
            val dir = File(verFile.parent)
            dir.mkdirs()
            verFile.createNewFile()
        }
        Upgrader.start()
    }

    fun checkUpgrade() {
        Toast
            .makeText(BusApplication.busContext, "版本号:${getAppVersion()}", Toast.LENGTH_SHORT)
            .show()

        GlobalScope.launch(Dispatchers.IO) {
           // Upgrader.start()
           // while (isActive) {
                val verRet = DevService.queryAppVer()
                android.util.Log.d("shinima","shinima")
                val appVer = getAppVersion()
                if (verRet is Result.Success) { //keep invoke util success
                    if (verRet.data.ver > appVer) {
                        upgrade(verRet.data.ver, verRet.data.sig, verRet.data.size)

                    }
                }
               // delay(1000 * 60)
            //}
        }
    }

    fun toUbusProvider(): Provider {
        return provider
    }

    private fun getAppVersion(): Int {
        val pm = BusApplication.busContext.packageManager
        val info = pm.getPackageInfo("com.wthink.hzgj", 0)
        return info.versionCode
    }

    object Upgrader {
        @Volatile
        private var working: Boolean = false

        fun start() {
            if (working) {
                return
            }
            working = true

            GlobalScope.launch(Dispatchers.IO) {
                //val dir = File("${Constants.ROOT}/app")
                val dir = File("${Constants.UPDATE_URL}")
                if (!dir.exists()) {
                    return@launch
                }

                while (isActive) {
                    val verList = dir.listFiles()
                    verList.sortBy {
                        it.name.split(".")[0]
                    }

                    if (verList.isEmpty()) {
                        return@launch
                    }

                    val file = verList.last()

                    val nameGroups = file.name.split(".")
                    val ver = nameGroups[0].toInt()
                    val sig = nameGroups[1]
                    val size = nameGroups[2].toLong()

                    if (ver == getAppVersion()) {
                        Log.debug("已是指定版本")
                        return@launch
                    }

                    val len = file.length()
                    if (len == size) {
                        if (HashUtil.checkMd5(file, sig)) {
                            upgrade(file)
                            return@launch
                        } else {
                            Log.debug("升级包文件签名不正确,重新下载")
                            file.delete()
                            file.createNewFile()
                        }
                    } else if (len > size) {
                        Log.debug("升级包文件大小超出,重新下载")
                        file.delete()
                        file.createNewFile()
                    } else {
                        var end = file.length() + Constants.SEG_SIZE
                        if (end > size) {
                            end = size
                        }
                        download(file, sig, file.length(), end)
                    }
                }
            }.invokeOnCompletion {
                working = false
                if (it != null) {
                    Log.debug("升级失败", it)
                }
            }
        }

        fun upgrade(file: File) {
            Log.debug("upgrade use file ${file.name}")
            if (!file.exists()) {
                return
            }

            val flagFile = File("${Constants.UPDATE_URL}/${Constants.UPDATE_FLAG}")
            if (!flagFile.exists()) {
                flagFile.createNewFile()
                try {
                    flagFile.createNewFile()
                    File(flagFile.absolutePath).appendText(file.name)
                } catch (e: Exception) {
                }
            }

            /* val localIntent = Intent(Intent.ACTION_VIEW)
            localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            localIntent.setDataAndType(
                Uri.fromFile(file),
                "application/vnd.android.package-archive"
            )
            BusApplication.busContext.startActivity(localIntent)*/
        }

        private suspend fun download(file: File, sig: String, from: Long, to: Long) {
            val ret = DevService.download(sig, from, to)
            if (ret is Result.Success) {
                file.appendBytes(ret.data.decodeBase64ToByteArray())
            } else {
                Log.debug(
                    "download ${file.name} from ${from} to ${to} failed",
                    (ret as Result.Error).exception
                )
                delay(1000)
            }
        }
    }
}